package com.yvan.periscope.controller;

import com.yvan.es.RestFulResult;
import com.yvan.es.SearchAction;
import com.yvan.periscope.domain.HistogramBean;
import com.yvan.periscope.service.SqlsService;
import com.yvan.periscope.service.SummaryService;
import com.yvan.periscope.service.UrlsService;
import com.yvan.platform.HttpJsonPayloadParser;
import com.yvan.platform.HttpParameterParser;
import com.yvan.platform.JsonWapper;
import com.yvan.platform.StringUtils;
import com.yvan.springmvc.ResultModel;
import io.searchbox.client.JestClient;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
public class AnalyticsSummaryController {

    @Autowired
    private JestClient jestClient;

    @Autowired
    private SqlsService sqlsService;

    @Autowired
    private UrlsService urlsService;

    @Autowired
    private SummaryService summaryService;

    @GetMapping("/analytics/summary.htm")
    public ModelAndView index(HttpServletRequest request) {
        HttpParameterParser parser = HttpParameterParser.newInstance(request);
        String TimeDay = parser.getString("TimeDay", "");

        ResultModel model = new ResultModel();
        model.put("TimeDay", TimeDay);

        return new ModelAndView("/summary.ftl", model);
    }

    @GetMapping("/analytics/sqls.htm")
    public ModelAndView sqlPage(HttpServletRequest request) {
        HttpParameterParser parser = HttpParameterParser.newInstance(request);
        String TimeDay = parser.getString("TimeDay", "");

        ResultModel model = new ResultModel();
        model.put("TimeDay", TimeDay);

        return new ModelAndView("/sqls.ftl", model);
    }

    /**
     * 打开urls页面
     * @param request
     * @return
     */
    @GetMapping("/analytics/urls.htm")
    public ModelAndView urlPage(HttpServletRequest request) {
        HttpParameterParser parser = HttpParameterParser.newInstance(request);
        String TimeDay = parser.getString("TimeDay", "");

        ResultModel model = new ResultModel();
        model.put("TimeDay", TimeDay);

        return new ModelAndView("/urls.ftl", model);
    }

    @RequestMapping("/analytics/summary.json")
    public Object data(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-summary-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.agg.DateHistogram("@timestamp", groupby, "yyyy-MM-dd HH:mm", dt1, dt2)
                .sum("requestCount")
                .max("concurrentMax")
                .sum("rdsCount")
                .sum("rdsCostTotal")
                .max("rdsCostMax")
                .sum("rdsResTotal")
                .sum("esCount")
                .sum("esCostTotal")
                .max("esCostMax")
                .sum("esResTotal")
                .max("jdbcActivePeak")
                .max("jdbcPoolingPeak")
                .sum("jdbcExecuteCount")
                .sum("jdbcErrorCount")
                .sum("startTransactionCount")
                .sum("jdbcCommitCount")
                .sum("jdbcRollbackCount")
                .sum("jdbcExecuteTimeMillis")
                .sum("jdbcFetchRowCount")
                .sum("jdbcUpdateCount")
                .sum("notEmptyWaitMillis")
                .sum("botCount");

        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        return jw;
    }

    /**
     * 分页获取URL数据接口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/urls.json")
    public Object getUrls(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-uris-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.query.filter.range("@timestamp",dt1.toString(),true,dt2.toString(),true);
        action.agg.terms("uri")
                .sum("requestCount")
                .max("concurrentMax")
                .sum("rdsCount")
                .sum("cost_sum")
                .max("cost_max")
                .sum("notEmptyWaitMillis")
                .sum("botCount").order("sum@uri@cost_sum","desc");



        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        return jw;
    }

    /**
     * 分页获取URL数据接口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/sqls.json")
    public Object getSqls(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-sqls-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.query.filter.range("@timestamp",dt1.toString(),true,dt2.toString(),true);
        action.agg.terms("sql")
                .sum("executeCount")
                .max("concurrentMax")
                .sum("cost_sum")
                .max("cost_max")
                .order("sum@sql@cost_sum","desc");



        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        return jw;
    }


    /**
     * summary页面汇总数据接口
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/summaryTotalData.json")
    public Object summaryTotalData(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-summary-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.query.filter.range("@timestamp", dt1.toString(), true, dt2.toString(), true);
        action.agg.sum("requestCount");
        action.agg.sum("esCount");
        action.agg.sum("rdsCount");
        action.agg.sum("jdbcExecuteCount");
        action.agg.max("concurrentMax");
        action.agg.sum("esResTotal");
        action.agg.sum("rdsResTotal");


        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        Object requestCount = jw.get("aggregations", "group_by@requestCount@requestCount");
        Object esCount = jw.get("aggregations", "group_by@esCount@esCount");
        Object rdsCount = jw.get("aggregations", "group_by@rdsCount@rdsCount");
        Object jdbcExecuteCount = jw.get("aggregations", "group_by@jdbcExecuteCount@jdbcExecuteCount");
        Object concurrentMax = jw.get("aggregations", "group_by@concurrentMax@concurrentMax");
        Object esResTotal = jw.get("aggregations", "group_by@esResTotal@esResTotal");
        Object rdsResTotal = jw.get("aggregations", "group_by@rdsResTotal@rdsResTotal");

        //summaryData是汇总数据
        List summaryData = new ArrayList();
        summaryData.add(requestCount);
        summaryData.add(esCount);
        summaryData.add(rdsCount);
        summaryData.add(jdbcExecuteCount);
        summaryData.add(concurrentMax);
        summaryData.add(esResTotal);
        summaryData.add(rdsResTotal);

        return summaryData;
    }

    /**
     * url页面汇总数据接口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/urlsSummaryData.json")
    public Object urlsSummaryData(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-uris-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.query.filter.range("@timestamp",dt1.toString(),true,dt2.toString(),true);
        action.agg.sum("cost_sum");
        action.agg.sum("requestCount");
        action.agg.max("cost_max");
        action.agg.max("concurrentMax");
        action.agg.terms("uri")
                .sum("requestCount")
                .max("concurrentMax")
                .sum("rdsCount")
                .sum("cost_sum")
                .max("cost_max")
                .sum("notEmptyWaitMillis")
                .sum("botCount").order("sum@uri@cost_sum","desc");
        action.agg.maxBucket("group_by@uri@uri.sum@uri@requestCount","maxOfrequestCountSum");


        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        Map resultMap = new HashMap();
        List resultList =jw.asList("aggregations", "group_by@uri@uri", "buckets").innerList;
        Object cost_max = jw.get("aggregations","group_by@cost_max@cost_max");
        Object cost_sum = jw.get("aggregations","group_by@cost_sum@cost_sum");
        Object requestCount = jw.get("aggregations","group_by@requestCount@requestCount");
        Object concurrentMax = jw.get("aggregations","group_by@concurrentMax@concurrentMax");
        Object maxOfrequestCountSum = jw.get("aggregations","group_by@maxOfrequestCountSum@buckets");

        //summaryData是汇总数据
        List summaryData = new ArrayList();
        summaryData.add(requestCount);
        summaryData.add(cost_sum);
        summaryData.add(cost_max);
        summaryData.add(concurrentMax);

        //chartDate是图表数据
        Map chartDate = new HashMap();
        chartDate.put("chartList",resultList);
        chartDate.put("maxOfCostMax",cost_max);
        chartDate.put("maxOfrequestCountSum",maxOfrequestCountSum);

        resultMap.put("chartDate",chartDate);
        resultMap.put("summaryData",summaryData);


        return resultMap;
    }

    /**
     * url页面汇总数据接口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/sqlsSummaryData.json")
    public Object sqlsSummaryData(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        SearchAction action = new SearchAction(log);
        action.index = "per-sqls-*";
        action.size = 0;

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String groupby = jwQ.asStr("groupby");
        if (StringUtils.isBlank(groupby)) {
            groupby = "day";
        }

        action.query.filter.range("@timestamp",dt1.toString(),true,dt2.toString(),true);
        action.agg.sum("cost_sum");
        action.agg.sum("executeCount");
        action.agg.max("cost_max");
        action.agg.max("concurrentMax");
        action.agg.terms("sql")
                .sum("executeCount")
                .max("concurrentMax")
                .sum("cost_sum")
                .avg("cost_sum")
                .max("cost_max")
                .order("sum@sql@cost_sum","desc");
        action.agg.maxBucket("group_by@sql@sql.sum@sql@executeCount","maxOfexecuteCountSum");


        RestFulResult r = action.search(jestClient);
        JsonWapper jw = r.getJsonWapper();
        String TimeDay = jwQ.asStr("TimeDay");
        jw.set("TimeDay", TimeDay);
        response.addHeader("Q", action.build().toString(false));
        Map resultMap = new HashMap();
        List resultList =jw.asList("aggregations", "group_by@sql@sql", "buckets").innerList;
        Object cost_max = jw.get("aggregations","group_by@cost_max@cost_max");
        Object cost_sum = jw.get("aggregations","group_by@cost_sum@cost_sum");
        Object executeCount = jw.get("aggregations","group_by@executeCount@executeCount");
        Object concurrentMax = jw.get("aggregations","group_by@concurrentMax@concurrentMax");
        Object maxOfexecuteCountSum = jw.get("aggregations","group_by@maxOfexecuteCountSum@buckets");
        //summaryData是汇总数据
        List summaryData = new ArrayList();
        summaryData.add(executeCount);
        summaryData.add(cost_sum);
        summaryData.add(cost_max);
        summaryData.add(concurrentMax);
        //chartDate是图表数据
        Map chartDate = new HashMap();
        chartDate.put("chartList",resultList);
        chartDate.put("maxOfCostMax",cost_max);
        chartDate.put("maxOfexecuteCountSum",maxOfexecuteCountSum);

        resultMap.put("chartDate",chartDate);
        resultMap.put("summaryData",summaryData);
        return resultMap;
    }


    /**
     * summary直方图接口
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/summaryHistogram.json")
    public Object summaryHistogram(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String histogramPrefix = jwQ.asStr("histogramPrefix");
        if (StringUtils.isNullOrEmpty(histogramPrefix)) {
            return null;
        }

        HistogramBean histogramBean = summaryService.getSummaryHistogram(histogramPrefix, dt1, dt2);

        return histogramBean;
    }

    /**
     * sql直方图接口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/sqlsHistogram.json")
    public Object sqlsHistogram(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String histogramPrefix = jwQ.asStr("histogramPrefix");
        if (StringUtils.isNullOrEmpty(histogramPrefix)) {
            return null;
        }

        HistogramBean histogramBean = sqlsService.getSqlsHistogram(histogramPrefix, dt1, dt2);

        return histogramBean;
    }

    /**
     * url直方图接口
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/analytics/urlsHistogram.json")
    public Object urlsHistogram(HttpServletRequest request, HttpServletResponse response) throws IOException {
        JsonWapper jwQ = new HttpJsonPayloadParser(request).getJsonWapper();

        //获取时间参数
        Map<String, DateTime> timeParamMap = getTimeParam(jwQ);
        DateTime dt1 = timeParamMap.get("dt1");
        DateTime dt2 = timeParamMap.get("dt2");

        String histogramPrefix = jwQ.asStr("histogramPrefix");
        if (StringUtils.isNullOrEmpty(histogramPrefix)) {
            return null;
        }

        HistogramBean histogramBean = urlsService.getUrlsHistogram(histogramPrefix, dt1, dt2);

        return histogramBean;
    }

    /**
     * 通用获取时间参数方法
     *
     * @param jwQ
     * @return
     * @throws IOException
     */
    private Map<String, DateTime> getTimeParam(JsonWapper jwQ) throws IOException {
        // 获取时间，默认查询所有
        DateTime now = DateTime.now();
        DateTime dt1 = now.plusDays(-1).withTimeAtStartOfDay();
        DateTime dt2 = now.withTime(23, 59, 59, 999);

        String TimeDay = jwQ.asStr("TimeDay");
        if (!StringUtils.isBlank(TimeDay)) {
            String[] vs = TimeDay.split("至");
            if (vs.length == 2) {
                DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
                dt1 = DateTime.parse(vs[0].trim(), format);
                dt2 = DateTime.parse(vs[1].trim(), format);
                dt2 = dt2.withSecondOfMinute(59).withMillisOfSecond(999);
            }
        }
        Map<String, DateTime> timeParamMap = new HashMap<>();
        timeParamMap.put("dt1", dt1);
        timeParamMap.put("dt2", dt2);
        return timeParamMap;
    }

}
